home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 49 / Amiga Format CD49 (2000-01-17)(Future Publishing)(GB)(Track 1 of 3)[!][issue 2000-02].iso / -serious- / misc / man2rtf / man2rtf.c < prev    next >
C/C++ Source or Header  |  1999-11-30  |  21KB  |  775 lines

  1. /*
  2.     Copyright 1990 by Norman Graham, Brandywine Softworks.
  3.  
  4.     Permission to use, copy, modify, and distribte this software for
  5.     any purpose and without fee is hereby granted, provided that the
  6.     above copyright notice appear in all copies and that both the
  7.     copyright notice and this permission notice and warranty disclaimer
  8.     appear in supporting documentation, and that the name of Brandywine
  9.     Softworks or Norman Graham not be used in advertising or publicity
  10.     pertaining to distribution of the software without specific, written
  11.     prior permission.
  12.  
  13.     Brandywine Softworks and Norman Graham disclaim all warranties with
  14.     regard to this software, including all implied warranties of
  15.     merchantability and fitness. In no event shall Brandywine Softworks
  16.     or Norman Graham be liable for any special, indirect, or consequential
  17.     damages or any damages whatsoever resulting from loss of use, data,
  18.     or profits, whether in an action of contract, negligence, or other
  19.     tortious action, arising out of or in connection with the use or
  20.     performance of this software.
  21. */
  22.  
  23. /******************************************************************************
  24.     File:   Man2RTF.c
  25.     Author: Norman Graham
  26.     Date:   2 September 1990
  27.  
  28.     Usage:  Man2RTF [-f|-h8|-h7] <Man.file >RTF.File
  29.  
  30.     Description:
  31.  
  32.         Man2RTF is a quick hack to convert a text file to Rich Text Format.
  33.         It converts some of the control sequences common in Un*x files into
  34.         the equivalent RTF character formatting. It converts the following
  35.         sequences:
  36.  
  37.             "a\ba"          =>  Bold 'a'
  38.             "a\ba\ba"       =>  Bold 'a'
  39.             "a\ba\ba\ba"    =>  Bold 'a'
  40.             "_\ba"          =>  Underlined 'a'
  41.             "_\ba\ba"       =>  Underlined Bold 'a'
  42.             "`"             =>  Typographer's Opening Single Quote
  43.             "'"             =>  Typographer's Closing Single Quote
  44.  
  45.         Any other string with a '\b' in it is written to stderr as an error.
  46.         The idea is that Man2RTF will tell you when you need to extend it
  47.         to handle control sequences not currently handled.
  48.  
  49.         Any non-control sequence is just copied to the RTF file.
  50.  
  51.  
  52.     Options:
  53.  
  54.         -f  Format the text with 10 point Courier and format the page
  55.             to display 66 lines on a vertical 8.5 inch by 11 inch page.
  56.             Margins are Top = 0.45 inch, Bottom = 0.45 inch, and
  57.             Left = 1.25 inches.
  58.  
  59.         -h8 Format the text with 8 point Courier and format the page
  60.             to display two columns of 66 lines on a horizontal 8.5 inch
  61.             by 11 inch page. Margins are Top = 0.21 inch, Bottom = 0.21 inch,
  62.             Left = 0.15 inch, and Right = 0.15 inch with 0.15 inch between
  63.             columns. This format is not as useful as '-h7'.
  64.  
  65.         -h7 Format the text with 7 point Courier and format the page
  66.             to display two columns of 66 lines on a horizontal 8.5 inch
  67.             by 11 inch page. Margins are Top = 0.9 inch, Bottom = 0.45 inch,
  68.             Left = 0.45 inch, and Right = 0.45 inch with 0.8 inch between
  69.             columns. This is a nice format because it provides a top margin
  70.             for binding and the space between columns is large enough that
  71.            you need not worry about the columns running together.
  72.  
  73.         If no option is specified, Man2RTF will only generate font style
  74.         information; it will not generate font name, font size, or
  75.         page formating information.
  76.  
  77.  
  78.     Caveats:
  79.  
  80.         If you use this tool on a Un*x box with the intention of
  81.         downloading the resulting file to your Mac, you need to
  82.         be aware that the resulting file probably contains typographer's
  83.         opening and closing quotes. These characters have values > 127
  84.         (i.e. their high bits are set), thus you'll need to make special
  85.         arangements to download the file. I'd suggest using mcvert
  86.         (available on sumex-aim) to convert the file to a macbinary
  87.         text file and then do a macbinary file transfer. As an alternative,
  88.         you could just nullify the typographer quote code by changing
  89.         kOpenSingleQuote to '`' and kCloseSingleQuote to '\''.
  90.  
  91.  
  92.     MPW build commands:
  93.  
  94.         In MPW, you can build Man2RTF by executing the following commands
  95.         directly from this file. You'll need to edit the Link command
  96.         to put the tool where you want it and to repair the line continuation
  97.         characters that undoubtly will be munged by transport over the
  98.         internet.
  99.  
  100.         C  "{Active}"
  101.  
  102.         Link -w -c 'MPS ' -t MPST       6
  103.             "{Active}".o                6
  104.             "{CLibraries}"StdClib.o     6
  105.             "{CLibraries}"CInterface.o  6
  106.             "{Libraries}"Stubs.o        6
  107.             "{CLibraries}"CRuntime.o    6
  108.             "{Libraries}"Interface.o    6
  109.             -o {MPW}Tools:LocalTools:Man2RTF
  110.  
  111.         Delete "{Active}".o
  112.  
  113.  
  114.     Porting:
  115.  
  116.         This program is written in ANSI C. If your compiler does not
  117.         support the ANSI C standard, you will need to modify this code.
  118.         Pay attention to the function prototypes, the new style function
  119.         definitions, and the string concatenation [used in calls to fprintf()
  120.         and puts()]. I believe most C compilers now support enum types,
  121.         but if yours doesn't you'll need to do some modifications here
  122.         as well.
  123.  
  124.         For MPW users. Watch out for munged characters in the Link
  125.         command (from above) and in the definitions of kOpenSingleQuote
  126.         and kCloseSingleQuote. These definitions contain characters
  127.         that are > 127 (i.e. their high bit is set).
  128.  
  129.  
  130.     Bugs:
  131.  
  132.         As with most quick hacks, the internals of this program are almost
  133.         completely undocumented. But it is a very simple program and
  134.         experienced C programmers should have no trouble following its
  135.         logic.
  136.  
  137.  
  138.     The following are some simple test strings:
  139.  
  140.         Clear text _U_n_d_e_r_l_i_n_e_ _t_e_x_t Clear text
  141.  
  142.         Clear text BBoolldd  tteexxtt Clear text
  143.  
  144.         Clear text _BB_oo_ll_dd_--_UU_nn_dd_ee_rr_ll_ii_nn_ee_  _tt_ee_xx_tt Clear text
  145.  
  146.         Clear text BBBaaaddd   ttteeexxxttt Clear text
  147.  
  148.         Clear text B_Ba_ad_d _ t_te_ex_xt_t Clear text
  149.  
  150. ******************************************************************************/
  151.  
  152. #include <stdio.h>
  153.  
  154.  
  155. /* Type Definitions... */
  156.  
  157. enum TypeStyle {
  158.     kUndefinedStyle,
  159.     kPlain,
  160.     kBold,
  161.     kExtraBold,
  162.     kUltraBold,
  163.     kUnderline,
  164.     kBoldUnderline
  165. };
  166. typedef enum TypeStyle TypeStyle;
  167.  
  168. enum PageFormat {
  169.     kUndefinedPage,
  170.     kDefaultPage,
  171.     kFullPage10Point,
  172.     kHalfPage8Point,
  173.     kHalfPage7Point
  174. };
  175. typedef enum PageFormat PageFormat;
  176.  
  177. typedef unsigned char Char;
  178.  
  179.  
  180. /* Function Prototypes... */
  181.  
  182. PageFormat ParseArguments (int, Char *[]);
  183.  
  184. void PrintHeader (PageFormat);
  185.  
  186. TypeStyle WhatStyle (Char *);
  187.  
  188. int CollectPlain         (Char *, Char *);
  189. int CollectBold          (Char *, Char *);
  190. int CollectExtraBold     (Char *, Char *);
  191. int CollectUltraBold     (Char *, Char *);
  192. int CollectUnderline     (Char *, Char *);
  193. int CollectBoldUnderline (Char *, Char *);
  194.  
  195.  
  196. /* Global Constants... */
  197.  
  198. #ifdef applec
  199. const Char      kOpenSingleQuote  = 'T';    /* Replace T with Option-]       */
  200. const Char      kCloseSingleQuote = 'U';    /* Replace U with Shift-Option-] */
  201. #else
  202. const Char      kOpenSingleQuote  = 0xD4;
  203. const Char      kCloseSingleQuote = 0xD5;
  204. #endif
  205.  
  206.  
  207. /* Entry Point... */
  208.  
  209. main (int argc, Char *argv[])
  210. {
  211.     int     indexInLine;
  212.     int     lengthInLine;
  213.     int     (*collectChars)(Char *, Char *);
  214.  
  215.     Char    *styleCommand;
  216.     Char    inLine [1024];      /* Actually, I believe these buffers need be */
  217.     Char    outLine [1024];     /*  only inLine [561], outLine [103], and    */
  218.     Char    pureChars [1024];   /*  putChars [81]. But hey, memory is cheap. */
  219.     Char    *fontCommand;
  220.  
  221.     PageFormat  fmt;
  222.  
  223.  
  224.     /* Parse the command line arguments */
  225.     fmt = ParseArguments (argc, argv);
  226.     if ( fmt == kUndefinedPage )
  227.     {
  228.         fprintf (stderr, "Invalid Argument\n");
  229.         fprintf (stderr,
  230.                  "Usage: %s [-f | -h8 | -h7] <Man.file >RTF.File\n",
  231.                  argv[0]);
  232.         return 0;
  233.     }
  234.  
  235.     /* Print the appropriate header. */
  236.     PrintHeader (fmt);
  237.  
  238.     /* Set up the font command string */
  239.     switch ( fmt )
  240.     {
  241.         case kFullPage10Point :
  242.             fontCommand = "\\f1\\fs20";
  243.             break;
  244.  
  245.         case kHalfPage8Point :
  246.             fontCommand = "\\f1\\fs16";
  247.             break;
  248.  
  249.         case kHalfPage7Point :
  250.             fontCommand = "\\f1\\fs14";
  251.             break;
  252.  
  253.         case kDefaultPage :
  254.         case kUndefinedPage :
  255.         default :
  256.             fontCommand = "";
  257.             break;
  258.     }
  259.  
  260.     /* Convert the file */
  261.     while ( gets(inLine) != NULL )
  262.     {
  263.         indexInLine = 0;
  264.         lengthInLine = strlen(inLine) + 1;      /* Process the '\0' also. */
  265.  
  266.         while ( indexInLine < lengthInLine )
  267.         {
  268.             switch ( WhatStyle (&inLine[indexInLine]) )
  269.             {
  270.                 case kPlain :
  271.                     collectChars = CollectPlain;
  272.                     styleCommand = "";
  273.                     break;
  274.  
  275.                 case kBold :
  276.                     collectChars = CollectBold;
  277.                     styleCommand = "\\b";
  278.                     break;
  279.  
  280.                 case kExtraBold :
  281.                     collectChars = CollectExtraBold;
  282.                     styleCommand = "\\b";
  283.                     break;
  284.  
  285.                 case kUltraBold :
  286.                     collectChars = CollectUltraBold;
  287.                     styleCommand = "\\b";
  288.                     break;
  289.  
  290.                 case kUnderline :
  291.                     collectChars = CollectUnderline;
  292.                     styleCommand = "\\ul";
  293.                     break;
  294.  
  295.                 case kBoldUnderline :
  296.                     collectChars = CollectBoldUnderline;
  297.                     styleCommand = "\\b\\ul";
  298.                     break;
  299.  
  300.                 case kUndefinedStyle :
  301.                 default :
  302.                     fprintf (stderr,
  303.                              "\nUnknown style returned from 'WhatStyle()'"
  304.                              "\nIndex is %d"
  305.                              "\nLine is \"%s\"\n",
  306.                              indexInLine + 1, inLine);
  307.                     inLine [indexInLine + 1] = '\0';
  308.                     fprintf (stderr,"Error is %s^--Here\n",inLine);
  309.                     return -1;
  310.             }
  311.  
  312.             indexInLine += collectChars (&inLine[indexInLine], pureChars);
  313.  
  314.             strcpy (outLine, "{\\plain");
  315.             strcat (outLine, fontCommand);
  316.             strcat (outLine, styleCommand);
  317.             strcat (outLine, " ");
  318.             strcat (outLine, pureChars);
  319.             strcat (outLine, "}");
  320.  
  321.             puts (outLine);
  322.         }
  323.     }
  324.  
  325.     /* Print trailer */
  326.     puts ("}");
  327.  
  328.     return 0;
  329. }
  330.  
  331.  
  332. PageFormat ParseArguments (int argc, Char *argv[])
  333. {
  334.     switch ( argc )
  335.     {
  336.         case 1 :
  337.             return kDefaultPage;
  338.  
  339.         case 2 :
  340.             if ( strcmp (argv[1], "-f") == 0 )
  341.                 return kFullPage10Point;
  342.             else if ( strcmp (argv[1], "-h8") == 0 )
  343.                 return kHalfPage8Point;
  344.             else if ( strcmp (argv[1], "-h7") == 0 )
  345.                 return kHalfPage7Point;
  346.             else
  347.                 return kUndefinedPage;
  348.  
  349.         default :
  350.             return kUndefinedPage;
  351.     }
  352. }
  353.  
  354. void PrintHeader (PageFormat fmt)
  355. {
  356.     puts ("{\\rtf0\\mac\\deff1");
  357.     puts ("{\\fonttbl{\\f0 \\fswiss Helvetica;}{\\f1 \\fmodern Courier;}}");
  358.  
  359.     switch ( fmt )
  360.     {
  361.         case kFullPage10Point :
  362.             puts ("\\paperw12240\\paperh15840\\margt648\\margb648"
  363.                   "\\margl1800\\margr0\\widowctrl\\ftnbj\\ftnrestart"
  364.                   "\\ftnstart1\\pgnstart1\\deftab720\\fracwidth\\sectd"
  365.                   "\\linemod0\\linex0\\cols1\\colsx863");
  366.             break;
  367.  
  368.         case kHalfPage8Point :
  369.             puts ("\\paperw15840\\paperh12240\\landscape\\margt144"
  370.                   "\\margb432\\margl144\\margr144\\widowctrl\\ftnbj"
  371.                   "\\ftnrestart\\ftnstart1\\pgnstart1\\deftab720"
  372.                   "\\fracwidth\\sectd\\linemod0\\linex0\\cols2\\colsx144");
  373.             break;
  374.  
  375.         case kHalfPage7Point :
  376.             puts ("\\paperw15840\\paperh12240\\landscape\\margt1440"
  377.                   "\\margb576\\margl720\\margr720\\widowctrl\\ftnbj"
  378.                   "\\ftnrestart\\ftnstart1\\pgnstart1\\deftab720"
  379.                   "\\fracwidth\\sectd\\linemod0\\linex0\\cols2\\colsx1080");
  380.             break;
  381.  
  382.         case kUndefinedPage :
  383.         default :
  384.             break;
  385.     }
  386.  
  387.     puts ("\\pard\\plain");
  388. }
  389.  
  390. TypeStyle WhatStyle ( Char *line )
  391. {
  392.     Char    c1, c2, c3, c4, c5, c6, c7;
  393.  
  394.     c1 = line [0];
  395.     c2 = line [1];
  396.     c3 = line [2];
  397.     c4 = line [3];
  398.     c5 = line [4];
  399.     c6 = line [5];
  400.     c7 = line [6];
  401.  
  402.     if ( c1 == c3 && c3 == c5 && c5 ==c7
  403.               && c2 == '\b' && c4 == '\b' && c6 == '\b'
  404.               && c1 != '\0' )
  405.         return kUltraBold;
  406.  
  407.     else if ( c1 == c3 && c3 == c5
  408.               && c2 == '\b' && c4 == '\b'
  409.               && c1 != '\0' )
  410.         return kExtraBold;
  411.  
  412.     else if ( c1 == '_' && c3 == c5
  413.               && c2 == '\b' && c4 == '\b'
  414.               && c3 != '\0' )
  415.         return kBoldUnderline;
  416.  
  417.     else if ( c1 == '_' && c2 == '\b' )
  418.         return kUnderline;
  419.  
  420.     else if ( c1 == c3 && c2 == '\b' && c1 != '\0' )
  421.         return kBold;
  422.  
  423.     else if ( c1 == '\b' || (c1 != '\0' && c2 == '\b') )
  424.         return kUndefinedStyle;
  425.  
  426.     else
  427.         return kPlain;
  428. }
  429.  
  430. int CollectPlain (Char *in, Char *out)
  431. {
  432.     Char    c;
  433.     Char    *startPos;
  434.  
  435.     startPos = in;
  436.  
  437.     while ( 1 )
  438.     {
  439.         switch ( c = *in++ )
  440.         {
  441.             case '\b' :
  442.                 *--out = '\0';
  443.                 return (in - startPos) - 2;
  444.  
  445.             case '\f' :
  446.                 *out++ = '\\';
  447.                 *out++ = 'p';
  448.                 *out++ = 'a';
  449.                 *out++ = 'g';
  450.                 *out++ = 'e';
  451.                 *out++ = ' ';
  452.                 break;
  453.  
  454.             case '`' :
  455.                 *out++ = kOpenSingleQuote;
  456.                 break;
  457.  
  458.             case '\'' :
  459.                 *out++ = kCloseSingleQuote;
  460.                 break;
  461.  
  462.             case '\0' :
  463.                 *out++ = '\\';
  464.                 *out++ = 'p';
  465.                 *out++ = 'a';
  466.                 *out++ = 'r';
  467.                 *out++ = ' ';
  468.                 *out   = '\0';
  469.                 return in - startPos;
  470.  
  471.             case '{' :
  472.                 *out++ = '\\';
  473.                 *out++ = '{';
  474.                 break;
  475.  
  476.             case '}' :
  477.                 *out++ = '\\';
  478.                 *out++ = '}';
  479.                 break;
  480.  
  481.             case '\\' :
  482.                 *out++ = '\\';
  483.                 *out++ = '\\';
  484.                 break;
  485.  
  486.             default :
  487.                 *out++ = c;
  488.                 break;
  489.         }
  490.     }
  491. }
  492.  
  493. int CollectBold (Char *in, Char *out)
  494. {
  495.     Char    c1, c2, c3;
  496.     Char    *startPos;
  497.  
  498.     startPos = in;
  499.  
  500.     while ( 1 )
  501.     {
  502.         c1 = in [0];
  503.         c2 = in [1];
  504.         c3 = in [2];
  505.  
  506.         if ( c1 != c3 || c2 != '\b' || c1 == '\0' )
  507.         {
  508.             *out = '\0';
  509.             return in - startPos;
  510.         }
  511.         else
  512.         {
  513.             in += 3;
  514.             switch ( c1 )
  515.             {
  516.                 case '`' :
  517.                     *out++ = kOpenSingleQuote;
  518.                     break;
  519.  
  520.                 case '\'' :
  521.                     *out++ = kCloseSingleQuote;
  522.                     break;
  523.  
  524.                 case '{' :
  525.                     *out++ = '\\';
  526.                     *out++ = '{';
  527.                     break;
  528.  
  529.                 case '}' :
  530.                     *out++ = '\\';
  531.                     *out++ = '}';
  532.                     break;
  533.  
  534.                 case '\\' :
  535.                     *out++ = '\\';
  536.                     *out++ = '\\';
  537.                     break;
  538.  
  539.                 default :
  540.                     *out++ = c1;
  541.                     break;
  542.             }
  543.         }
  544.     }
  545. }
  546.  
  547. int CollectExtraBold (Char *in, Char *out)
  548. {
  549.     Char    c1, c2, c3, c4, c5;
  550.     Char    *startPos;
  551.  
  552.     startPos = in;
  553.  
  554.     while ( 1 )
  555.     {
  556.         c1 = in [0];
  557.         c2 = in [1];
  558.         c3 = in [2];
  559.         c4 = in [3];
  560.         c5 = in [4];
  561.  
  562.         if ( c1 != c3 || c3 != c5
  563.              || c2 != '\b' || c4 != '\b'
  564.              || c1 == '\0' )
  565.         {
  566.             *out = '\0';
  567.             return in - startPos;
  568.         }
  569.         else
  570.         {
  571.             in += 5;
  572.             switch ( c1 )
  573.             {
  574.                 case '`' :
  575.                     *out++ = kOpenSingleQuote;
  576.                     break;
  577.  
  578.                 case '\'' :
  579.                     *out++ = kCloseSingleQuote;
  580.                     break;
  581.  
  582.                 case '{' :
  583.                     *out++ = '\\';
  584.                     *out++ = '{';
  585.                     break;
  586.  
  587.                 case '}' :
  588.                     *out++ = '\\';
  589.                     *out++ = '}';
  590.                     break;
  591.  
  592.                 case '\\' :
  593.                     *out++ = '\\';
  594.                     *out++ = '\\';
  595.                     break;
  596.  
  597.                 default :
  598.                     *out++ = c1;
  599.                     break;
  600.             }
  601.         }
  602.     }
  603. }
  604.  
  605. int CollectUltraBold (Char *in, Char *out)
  606. {
  607.     Char    c1, c2, c3, c4, c5, c6, c7;
  608.     Char    *startPos;
  609.  
  610.     startPos = in;
  611.  
  612.     while ( 1 )
  613.     {
  614.         c1 = in [0];
  615.         c2 = in [1];
  616.         c3 = in [2];
  617.         c4 = in [3];
  618.         c5 = in [4];
  619.         c6 = in [5];
  620.         c7 = in [6];
  621.  
  622.         if ( c1 != c3 || c3 != c5 || c5 != c7
  623.              || c2 != '\b' || c4 != '\b' || c6 != '\b'
  624.              || c1 == '\0' )
  625.         {
  626.             *out = '\0';
  627.             return in - startPos;
  628.         }
  629.         else
  630.         {
  631.             in += 7;
  632.             switch ( c1 )
  633.             {
  634.                 case '`' :
  635.                     *out++ = kOpenSingleQuote;
  636.                     break;
  637.  
  638.                 case '\'' :
  639.                     *out++ = kCloseSingleQuote;
  640.                     break;
  641.  
  642.                 case '{' :
  643.                     *out++ = '\\';
  644.                     *out++ = '{';
  645.                     break;
  646.  
  647.                 case '}' :
  648.                     *out++ = '\\';
  649.                     *out++ = '}';
  650.                     break;
  651.  
  652.                 case '\\' :
  653.                     *out++ = '\\';
  654.                     *out++ = '\\';
  655.                     break;
  656.  
  657.                 default :
  658.                     *out++ = c1;
  659.                     break;
  660.             }
  661.         }
  662.     }
  663. }
  664.  
  665. int CollectUnderline (Char *in, Char *out)
  666. {
  667.     Char    c1, c2, c3;
  668.     Char    *startPos;
  669.  
  670.     startPos = in;
  671.  
  672.     while ( 1 )
  673.     {
  674.         c1 = in [0];
  675.         c2 = in [1];
  676.         c3 = in [2];
  677.  
  678.         if ( c1 != '_' || c2 != '\b' || c3 == '\0' )
  679.         {
  680.             *out = '\0';
  681.             return in - startPos;
  682.         }
  683.         else
  684.         {
  685.             in += 3;
  686.             switch ( c3 )
  687.             {
  688.                 case '`' :
  689.                     *out++ = kOpenSingleQuote;
  690.                     break;
  691.  
  692.                 case '\'' :
  693.                     *out++ = kCloseSingleQuote;
  694.                     break;
  695.  
  696.                 case '{' :
  697.                     *out++ = '\\';
  698.                     *out++ = '{';
  699.                     break;
  700.  
  701.                 case '}' :
  702.                     *out++ = '\\';
  703.                     *out++ = '}';
  704.                     break;
  705.  
  706.                case '\\' :
  707.                     *out++ = '\\';
  708.                     *out++ = '\\';
  709.                     break;
  710.  
  711.                 default :
  712.                     *out++ = c3;
  713.                     break;
  714.             }
  715.         }
  716.     }
  717. }
  718.  
  719. int CollectBoldUnderline (Char *in, Char *out)
  720. {
  721.     Char    c1, c2, c3, c4, c5;
  722.     Char    *startPos;
  723.  
  724.     startPos = in;
  725.  
  726.     while ( 1 )
  727.     {
  728.         c1 = in [0];
  729.         c2 = in [1];
  730.         c3 = in [2];
  731.         c4 = in [3];
  732.         c5 = in [4];
  733.  
  734.         if ( c1 != '_' || c2 != '\b' || c4 != '\b' || c3 != c5 || c3 == '\0' )
  735.         {
  736.             *out = '\0';
  737.             return in - startPos;
  738.         }
  739.         else
  740.         {
  741.             in += 5;
  742.             switch ( c3 )
  743.             {
  744.                 case '`' :
  745.                     *out++ = kOpenSingleQuote;
  746.                     break;
  747.  
  748.                 case '\'' :
  749.                     *out++ = kCloseSingleQuote;
  750.                     break;
  751.  
  752.                 case '{' :
  753.                     *out++ = '\\';
  754.                     *out++ = '{';
  755.                     break;
  756.  
  757.                 case '}' :
  758.                     *out++ = '\\';
  759.                     *out++ = '}';
  760.                     break;
  761.  
  762.                 case '\\' :
  763.                     *out++ = '\\';
  764.                     *out++ = '\\';
  765.                     break;
  766.  
  767.                 default :
  768.                     *out++ = c3;
  769.                     break;
  770.             }
  771.         }
  772.     }
  773. }
  774.                        
  775.